package jalgebrava.group.groups;

import static jalgebrava.util.collections.IterableUtil.*;
import jalgebrava.group.Group;

import java.util.HashMap;
class RelabeledGroupFactory {
	@SuppressWarnings("unused")
	private final static RelabeledGroupFactory instance = new RelabeledGroupFactory();
	private RelabeledGroupFactory() {
		// hidden
	}
	final static <G> Group<Integer> mk(final Group<G> group) {
		final int size = group.size();
		int maxSize = 1000;

		if (size > maxSize) {
			throw new RuntimeException("Group too large to be abstracted! " + maxSize);
		}
		
		final HashMap<G, Integer> fromG = new HashMap<G, Integer>();
		final HashMap<Integer, G> toG = new HashMap<Integer, G>();
		int i = 0;
		for (G g: group) {			
			
			fromG.put(g, i);
			toG.put(i, g);
			
			i++;
		}
		
		
		return new AbstractGroup<Integer>(group.getDescription()+"[relabeled]", integerRange(0, size), size) {

			@Override
			public Integer unit() {
				return fromG.get(group.unit());
			}

			@Override
			public Integer inv(Integer x) {
				
				return fromG.get(group.inv(toG.get(x)));
			}

			@Override
			public Integer mul(Integer x, Integer y) {				
				return fromG.get(group.mul(toG.get(x), toG.get(y)));
			}

			@Override
			public boolean contains(Integer x) {
				return 0 <= x && x < size; 
			}
			
			
		};
	}
}
